原生javascript写一个弹窗消息提醒插件 您所在的位置:网站首页 javascript插件 pageloader 原生javascript写一个弹窗消息提醒插件

原生javascript写一个弹窗消息提醒插件

2023-03-12 21:57| 来源: 网络整理| 查看: 265

原生javascript写一个弹窗消息提醒插件。喏,就是这么一个效果。

原生javascript写一个弹窗消息提醒插件-字节智造需求分析当消息被触发的时候,会有一个自上而下的淡入过程。在持续了一段时间后会自动的消失,或者是需要用户来手动的点击关闭按钮。在消息消失的时候,会有一个自下而上的淡出过程。消息是可以叠加弹出的,最新的消息会排在消息列表的最后面。当前面的消息消失后,后面的消息会有一个向上滑动效果。

然后消息本身是有三部分组成

消息图标,用来区分不同类型的消息。消息文本。关闭按钮,并不是所有消息都需要关闭按钮。实现样式

那么,不管我们是用原生 js 还是 vue,首先呢,我们都需要把这个消息的基本样式给写出来,然后再通过 js 来控制消息的弹出和关闭。所以,我们先来写 html 和 css。

这是一条正经的消息~ 这是一条正经的消息~ /* message.css */ #message-container { position: fixed; left: 0; top: 0; right: 0; /* 采用flex弹性布局,让容器内部的所有消息可以水平居中,还能任意的调整宽度 */ display: flex; flex-direction: column; align-items: center; } #message-container .message { background: #fff; margin: 10px 0; padding: 0 10px; height: 40px; box-shadow: 0 0 10px 0 #eee; font-size: 14px; border-radius: 3px; /* 让消息内部的三个元素(图标、文本、关闭按钮)可以垂直水平居中 */ display: flex; align-items: center; } #message-container .message .text { color: #333; padding: 0 20px 0 5px; } #message-container .message .close { cursor: pointer; color: #999; } /* 给每个图标都加上不同的颜色,用来区分不同类型的消息 */ #message-container .message .icon-info { color: #0482f8; } #message-container .message .icon-error { color: #f83504; } #message-container .message .icon-success { color: #06a35a; } #message-container .message .icon-warning { color: #ceca07; } #message-container .message .icon-loading { color: #0482f8; }

大概是这么一个效果

原生javascript写一个弹窗消息提醒插件-字节智造实现动画

接下来要做的就是这个消息的弹出和消失动画,我们还是用 css 来实现。

想要在 css 里边实现自定义的动画,首先需要用 @keyframes 来定义一个动画规则,然后再通过 animation 属性把动画应用到某个元素上就可以了。

所谓的动画规则其实就是一个动画序列,或者可以理解为一个个的关键帧,而关键帧的内部就是你想改变的 css 属性,你可以在关键帧里边写上几乎任何的 css 属性,当动画被应用的时候,这些 css 属性就会根据各个关键帧做出相应的变换。

那我们先用 @keyframes 来写一个动画规则吧

/* message.css */ /* 这个动画规则我们就叫做message-move-in吧,随后我们会用animation属性在某个元素上应用这个动画规则。 */ @keyframes message-move-in { 0% { /* 前边分析过了,弹出动画是一个自上而下的淡入过程 */ /* 所以在动画初始状态要把元素的不透明度设置为0,在动画结束的时候再把不透明度设置1,这样就会实现一个淡入动画 */ opacity: 0; /* 那么“自上而下”这个动画可以用“transform”变换属性结合他的“translateY”上下平移函数来完成 */ /* translateY(-100%)表示动画初始状态,元素在实际位置上面“自身一个高度”的位置。 */ transform: translateY(-100%); } 100% { opacity: 1; /* 平移到自身位置 */ transform: translateY(0); } }

然后我们再定义一个和 message 元素同级的类 move-in,把 message-move-in 这个动画规则给应用到 move-in 类上,这样我们需要让哪个消息弹出,就只需要在消息的类上加一个 move-in 就行。

/* message.css */ #message-container .message.move-in { /* animation属性是用来加载某个动画规则 请参考 https://developer.mozilla.org/zh-CN/docs/Web/CSS/animation */ animation: message-move-in 0.3s ease-in-out; }

我们来看下怎么用这个 move-in:

原生javascript写一个弹窗消息提醒插件-字节智造

可以看到,只需要在某个 message 上追加一个 move-in 就能实现弹出动画。那么,消失动画也是一个套路,只不过跟弹出动画反过来而已。

/* message.css */ @keyframes message-move-out { 0% { opacity: 1; transform: translateY(0); } 100% { opacity: 0; transform: translateY(-100%); } } #message-container .message.move-out { animation: message-move-out 0.3s ease-in-out; /* 让动画结束后保持结束状态 */ animation-fill-mode: forwards; }

animation-fill-mode: forwards; 这个是干嘛的呢?因为动画结束后默认会回到元素的最初状态,在这里表现的是消失后又出现了,如图:

原生javascript写一个弹窗消息提醒插件-字节智造

所以 animation-fill-mode: forwards; 是为了让动画结束后保持这个结束状态,也就是不在显示了。

编写 js 插件

那么,在写 js 之前呢,我们先来思考一下,如果你是插件的使用者,你想怎么来调用这个插件?

我们的插件很简单,就是在需要的时候弹出一个消息,假设插件他提供给我们的是一个类,就叫做 Message 吧,并且他内部有一个 show 方法,那么只要使用者实例化这个类后,调用他的 show 方法,然后传入不同的参数就可以弹出一个消息了。而且我们所实例化的对象可以是全局唯一的。

// message可以定义为全局对象,项目中可以直接调用。 const message = new Message(); message.show({ type: 'success', text: '点个关注不迷路~' });

所以呢,我们要先写一个 Message 类,并且必须要实现一个 show 方法。

/* message.js */ class Message { constructor() { } show({ type = 'info', text = '' }) { } }

这里我直接用了 es6 的 class 关键词,其实他的内部还是原型链的形式。用 class 呢,可以让我们更直观的了解这个类。

根据我们在第一部分的分析,所有的消息元素都是需要在 js 中创建的,所以我们不需要使用者来写任何 html 代码,那么我们只需要在对象被实例化 new Message() 的时候,就去创建消息容器 message-container,后续在调用 show 方法时候,直接把消息插入到 message-container 内部即可。

/* message.js */ class Message { /** * 构造函数会在实例化的时候自动执行 */ constructor() { const containerId = 'message-container'; // 检测下html中是否已经有这个message-container元素 this.containerEl = document.getElementById(containerId); if (!this.containerEl) { // 创建一个Element对象,也就是创建一个id为message-container的dom节点 this.containerEl = document.createElement('div'); this.containerEl.id = containerId; // 把message-container元素放在html的body末尾 document.body.appendChild(this.containerEl); } } show({ type = 'info', text = '' }) { } }

这样,我们调用 const message = new Message() 的时候会在 dom 中自动的插入一个 message-container 节点。

那么,最重要的还是我们的 show 方法:

创建一个消息节点,并把它追加到 message-container 容器的末尾。设定一个时间,在这个时间结束后自动的将消息移除。监听 “关闭按钮” 的 click 事件,来让用户可以手动的移除消息。

我们一步一步来。

4.1 创建一个消息节点,并把它追加到 message-container 容器的末尾。

class Message { // 省略... show({ type = 'info', text = '' }) { // 创建一个Element对象 let messageEl = document.createElement('div'); // 设置消息class,这里加上move-in可以直接看到弹出效果 messageEl.className = 'message move-in'; // 消息内部html字符串 messageEl.innerHTML = ` ${text} `; // 追加到message-container末尾 // this.containerEl属性是我们在构造函数中创建的message-container容器 this.containerEl.appendChild(messageEl); }

我们来调用下试试~

弹窗消息提醒 // message可以定义为全局对象,项目中可以直接调用。 const message = new Message(); document.querySelector('.btn').addEventListener('click', () => { message.show({ type: 'success', text: '点个关注不迷路~' }); }); 原生javascript写一个弹窗消息提醒插件-字节智造

4.2 设定一个时间,在这个时间结束后自动的将消息移除。

// message.js class Message { // 省略... show({ type = 'info', text = '', duration = 2000 }) { // 省略... // 用setTimeout来做一个定时器 setTimeout(() => { // Element对象内部有一个remove方法,调用之后可以将该元素从dom树种移除! messageEl.remove(); }, duration); } }原生javascript写一个弹窗消息提醒插件-字节智造

可以看到,消息在过了 2 秒后,自动的从 dom 树中移除了,不过呢并没有动画,还记得前边我们写了 move-out 类吗?这个类和 message 是同级的。现在我们只需要在定时结束后把这个类应用到 message 元素上就行。

// message.js class Message { // 省略... show({ type = 'info', text = '', duration = 2000 }) { // 省略... // 用setTimeout来做一个定时器 setTimeout(() => { // 首先把move-in这个弹出动画类给移除掉,要不然会有问题,可以自己测试下 messageEl.className = messageEl.className.replace('move-in', ''); // 增加一个move-out类 messageEl.className += 'move-out'; // 这个地方是监听动画结束事件,在动画结束后把消息从dom树中移除。 // 如果你是在增加move-out后直接调用messageEl.remove,那么你不会看到任何动画效果 messageEl.addEventListener('animationend', () => { // Element对象内部有一个remove方法,调用之后可以将该元素从dom树种移除! messageEl.remove(); }); }, duration); } }

注意观察 dom 树的变化:

原生javascript写一个弹窗消息提醒插件-字节智造

4.3 监听 “关闭按钮” 的 click 事件,来让用户可以手动的移除消息。

有时候呢,我们希望消息能够一直展示,直到用户来手动的关闭掉,那么首先我们要加一个参数,用来控制是否展示这个关闭按钮。

// message.js class Message { // 省略... show({ type = 'info', text = '', duration = 2000, closeable = false }) { // 创建一个Element对象 let messageEl = document.createElement('div'); // 设置消息class,这里加上move-in可以直接看到弹出效果 messageEl.className = 'message move-in'; // 消息内部html字符串 messageEl.innerHTML = ` ${text} `; // 是否展示关闭按钮 if (closeable) { // 创建一个关闭按钮 let closeEl = document.createElement('div'); closeEl.className = 'close icon icon-close'; // 把关闭按钮追加到message元素末尾 messageEl.appendChild(closeEl); // 监听关闭按钮的click事件,触发后将调用我们的close方法 // 我们把刚才写的移除消息封装为一个close方法 closeEl.addEventListener('click', () => { this.close(messageEl) }); } // 追加到message-container末尾 // this.containerEl属性是我们在构造函数中创建的message-container容器 this.containerEl.appendChild(messageEl); // 只有当duration大于0的时候才设置定时器,这样我们的消息就会一直显示 if (duration > 0) { // 用setTimeout来做一个定时器 setTimeout(() => { this.close(messageEl); }, duration); } } /** * 关闭某个消息 * 由于定时器里边要移除消息,然后用户手动关闭事件也要移除消息,所以我们直接把移除消息提取出来封装成一个方法 * @param {Element} messageEl */ close(messageEl) { // 首先把move-in这个弹出动画类给移除掉,要不然会有问题,可以自己测试下 messageEl.className = messageEl.className.replace('move-in', ''); // 增加一个move-out类 messageEl.className += 'move-out'; // 这个地方是监听动画结束事件,在动画结束后把消息从dom树中移除。 // 如果你是在增加move-out后直接调用messageEl.remove,那么你不会看到任何动画效果 messageEl.addEventListener('animationend', () => { // Element对象内部有一个remove方法,调用之后可以将该元素从dom树种移除! messageEl.remove(); }); } }

我们来调用下试试~

弹窗消息提醒 // message可以定义为全局对象,项目中可以直接调用。 const message = new Message(); document.querySelector('.btn').addEventListener('click', () => { message.show({ type: 'warning', text: '点我旁边的叉叉试试', duration: 0, // 不会自动消失 closeable: true, // 可手动关闭 }); }); 原生javascript写一个弹窗消息提醒插件-字节智造

其实已经写的差不多了,不过还是有一些小问题,比如当我们弹出两个甚至更多消息的时候,如果前边的消息消失后,下面的消息会直接跳到上面的位置,很僵硬,没有任何的滑动,如图:

原生javascript写一个弹窗消息提醒插件-字节智造

我们可以通过 css 的 transition 属性来让 meesage 的高度逐渐变小,这样下面的元素就会根据变化来逐渐上移。

/* message.css */ /* 省略... */ #message-container .message { background: #fff; margin: 10px 0; padding: 0 10px; height: 40px; box-shadow: 0 0 10px 0 #ccc; font-size: 14px; border-radius: 3px; /* 让消息内部的三个元素(图标、文本、关闭按钮)可以垂直水平居中 */ display: flex; align-items: center; /* 增加一个过渡属性,当message元素的高度和margin变化时候将会有一个过渡动画 */ transition: height 0.2s ease-in-out, margin 0.2s ease-in-out; } /* 省略... */

然后我们只需要在 Message 类的 close 方法中做一下改变:

close(messageEl) { // 首先把move-in这个弹出动画类给移除掉,要不然会有问题,可以自己测试下 messageEl.className = messageEl.className.replace('move-in', ''); // 增加一个move-out类 messageEl.className += 'move-out'; // move-out动画结束后把元素的高度和边距都设置为0 // 由于我们在css中设置了transition属性,所以会有一个过渡动画 messageEl.addEventListener('animationend', () => { messageEl.setAttribute('style', 'height: 0; margin: 0'); }); // 这个地方是监听transition的过渡动画结束事件,在动画结束后把消息从dom树中移除。 messageEl.addEventListener('transitionend', () => { // Element对象内部有一个remove方法,调用之后可以将该元素从dom树种移除! messageEl.remove(); }); }

看效果:

原生javascript写一个弹窗消息提醒插件-字节智造结尾

好了,基本上已经写好了,不过为了各个浏览器的兼容性,建议大家用 babel 转码,如果想发布,可以用 webpack 把 js 和 css 一块打包。

不过我们还是少考虑了一个场景,现在的关闭消息都是对象内部调用 close 方法来实现,如果我们希望外部能够控制消息的关闭呢,比如我请求服务器时候弹出一个 loading 的消息,现在服务器返回数据后,我怎么来关闭这个消息呢。很简单,各位自行实现吧!

本文转自laravuel

版权声明:著作权归作者所有。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有